package com.tsfyun.scm.service.impl.customs;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.enums.BillTypeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.extension.OrderItem;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.common.base.util.TypeUtils;
import com.tsfyun.scm.dto.customs.DeclarationTempDTO;
import com.tsfyun.scm.dto.customs.DeclarationTempQTO;
import com.tsfyun.scm.entity.customs.DeclarationTemp;
import com.tsfyun.scm.entity.system.StatusHistory;
import com.tsfyun.scm.mapper.customs.DeclarationTempMapper;
import com.tsfyun.scm.service.customs.IDeclarationTempService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.customs.DeclarationTempSimpleVO;
import com.tsfyun.scm.vo.customs.DeclarationTempVO;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 报关单模板 服务实现类
 * </p>
 *
 *
 * @since 2020-04-24
 */
@Service
public class DeclarationTempServiceImpl extends ServiceImpl<DeclarationTemp> implements IDeclarationTempService {

    @Autowired
    private DeclarationTempMapper declarationTempMapper;

    @Override
    public void add(DeclarationTempDTO dto) {
        //如果前端未传是否默认，则默认为未勾选不默认
        dto.setIsDefault(TypeUtils.castToBoolean(dto.getIsDefault(),Boolean.FALSE));
        DeclarationTemp declarationTemp = beanMapper.map(dto,DeclarationTemp.class);
        declarationTemp.setDisabled(Boolean.FALSE);
        //如果勾选了默认，则需要取消以前设置的默认
        if(Objects.equals(dto.getIsDefault(),Boolean.TRUE)) {
            handleOldDefault(dto.getBillType());
        }
        try {
            super.saveNonNull(declarationTemp);
        } catch (DuplicateKeyException e) {
            throw new ServiceException("该模板名称已经存在，请更换为便于您识别的模板名称");
        }
    }

    @Override
    public void edit(DeclarationTempDTO dto) {
        DeclarationTemp declarationTemp = super.getById(dto.getId());
        Optional.ofNullable(declarationTemp).orElseThrow(()->new ServiceException("报关单模板不存在"));
        //如果前端未传是否默认，则默认为未勾选不默认
        dto.setIsDefault(TypeUtils.castToBoolean(dto.getIsDefault(),Boolean.FALSE));
        //如果由非默认变为默认则需要处理之前设置的默认的，如果是否默认未变更则无需处理；单据类型的变更了也要处理
        if (((!Objects.equals(Boolean.TRUE,declarationTemp.getIsDefault()) && Objects.equals(dto.getBillType(),declarationTemp.getBillType()))
            || !Objects.equals(dto.getBillType(),declarationTemp.getBillType()) ) && Objects.equals(Boolean.TRUE,dto.getIsDefault())) {
            handleOldDefault(declarationTemp.getBillType());
        }
        declarationTemp.setBillType(dto.getBillType());
        declarationTemp.setTempName(dto.getTempName());
        declarationTemp.setCusTrafModeCode(dto.getCusTrafModeCode());
        declarationTemp.setCusTrafModeName(dto.getCusTrafModeName());
        declarationTemp.setSupvModeCdde(dto.getSupvModeCdde());
        declarationTemp.setSupvModeCddeName(dto.getSupvModeCddeName());
        declarationTemp.setCutModeCode(dto.getCutModeCode());
        declarationTemp.setCutModeName(dto.getCutModeName());
        declarationTemp.setCusTradeCountryCode(dto.getCusTradeCountryCode());
        declarationTemp.setCusTradeCountryName(dto.getCusTradeCountryName());
        declarationTemp.setDistinatePortCode(dto.getDistinatePortCode());
        declarationTemp.setDistinatePortName(dto.getDistinatePortName());
        declarationTemp.setCustomMasterCode(dto.getCustomMasterCode());
        declarationTemp.setCustomMasterName(dto.getCustomMasterName());
        declarationTemp.setWrapTypeCode(dto.getWrapTypeCode());
        declarationTemp.setWrapTypeName(dto.getWrapTypeName());
        declarationTemp.setCusTradeNationCode(dto.getCusTradeNationCode());
        declarationTemp.setCusTradeNationName(dto.getCusTradeNationName());
        declarationTemp.setCiqEntyPortCode(dto.getCiqEntyPortCode());
        declarationTemp.setCiqEntyPortName(dto.getCiqEntyPortName());
        declarationTemp.setGoodsPlace(dto.getGoodsPlace());
        declarationTemp.setDestPortCode(dto.getDestPortCode());
        declarationTemp.setDestPortName(dto.getDestPortName());
        declarationTemp.setDutyMode(dto.getDutyMode());
        declarationTemp.setDutyModeName(dto.getDutyModeName());
        declarationTemp.setDistrictCode(dto.getDistrictCode());
        declarationTemp.setDistrictName(dto.getDistrictName());
        declarationTemp.setCiqDestCode(dto.getCiqDestCode());
        declarationTemp.setCiqDestName(dto.getCiqDestName());
        declarationTemp.setIePortCode(dto.getIePortCode());
        declarationTemp.setIePortName(dto.getIePortName());
        declarationTemp.setMarkNo(dto.getMarkNo());
        declarationTemp.setIsDefault(dto.getIsDefault());
        declarationTemp.setDestinationCountry(dto.getDestinationCountry());
        declarationTemp.setDestinationCountryName(dto.getDestinationCountryName());
        try {
            super.updateById(declarationTemp);
        } catch (DuplicateKeyException e) {
            throw new ServiceException("该模板名称已经存在，请更换为便于您识别的模板名称");
        }
    }

    @Override
    public void updateDisabled(Long id, Boolean disabled) {
        DeclarationTemp declarationTemp = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(declarationTemp),new ServiceException("报关单模板不存在"));
        if(Objects.equals(disabled,Boolean.TRUE)&&Objects.equals(declarationTemp.getIsDefault(),Boolean.TRUE)){
            throw new ServiceException("当前报关模板为默认模板禁止禁用");
        }
        DeclarationTemp update = new DeclarationTemp();
        update.setDisabled(disabled);
        declarationTempMapper.updateByExampleSelective(update, Example.builder(DeclarationTemp.class).where(
                WeekendSqls.<DeclarationTemp>custom().andEqualTo(DeclarationTemp::getId,id)
        ).build());
    }

    @Override
    public DeclarationTempVO detail(Long id) {
        DeclarationTemp declarationTemp = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(declarationTemp),new ServiceException("报关单模板不存在"));
        return beanMapper.map(declarationTemp,DeclarationTempVO.class);
    }

    @Override
    public List<DeclarationTempSimpleVO> selectByBillType(String billType,String tempName) {
        Example example = Example.builder(DeclarationTemp.class).where(TsfWeekendSqls.<DeclarationTemp>custom()
                .andEqualTo(false,DeclarationTemp::getBillType,billType)
                .andLike(true,DeclarationTemp::getTempName,tempName)
                .andEqualTo(false,DeclarationTemp::getDisabled,Boolean.FALSE)).build();
        example.setOrderByClause("is_default desc,date_created desc");
        List<DeclarationTemp> list = declarationTempMapper.selectByExampleAndRowBounds(example, new RowBounds(0, 20));
        return beanMapper.mapAsList(list,DeclarationTempSimpleVO.class);
    }

    @Override
    public PageInfo<DeclarationTemp> pageList(DeclarationTempQTO qto) {
        TsfWeekendSqls wheres = TsfWeekendSqls.<DeclarationTemp>custom().andEqualTo(true,DeclarationTemp::getBillType,qto.getBillType())
                .andLike(true,DeclarationTemp::getTempName,qto.getTempName());
        return super.pageList(qto.getPage(),qto.getLimit(),wheres, Lists.newArrayList(OrderItem.desc("isDefault"),OrderItem.desc("dateCreated")));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeById(Long id) {
        DeclarationTemp declarationTemp = super.getById(id);
        Optional.ofNullable(declarationTemp).orElseThrow(()->new ServiceException("报关单模板不存在"));
        super.removeById(id);
    }

    @Override
    public void setDefault(Long id, Boolean isDefault) {
        DeclarationTemp declarationTemp = super.getById(id);
        Optional.ofNullable(declarationTemp).orElseThrow(()->new ServiceException("报关单模板不存在"));
        declarationTemp.setIsDefault(isDefault);
        if(Objects.equals(Boolean.TRUE,isDefault)) {
            //取消以前设置的默认，按单据类型
            handleOldDefault(declarationTemp.getBillType());
        } else {
            //以前是非默认，现在置为默认，则需要取消以前的默认如果存在的话
            declarationTemp.setIsDefault(Boolean.FALSE);
        }
        super.updateById(declarationTemp);
    }

    @Override
    public DeclarationTemp obtanDefault(BillTypeEnum billType) {
        DeclarationTemp query = new DeclarationTemp();
        query.setBillType(billType.getCode());
        query.setIsDefault(Boolean.TRUE);
        return declarationTempMapper.selectOne(query);
    }

    @Override
    public List<DeclarationTempSimpleVO> obtanDefaultList(BillTypeEnum billType) {
        DeclarationTemp query = new DeclarationTemp();
        query.setBillType(billType.getCode());
        query.setDisabled(Boolean.FALSE);
        List<DeclarationTemp> declarationTemps = declarationTempMapper.select(query);
        List<DeclarationTempSimpleVO> list = Lists.newArrayList();
        if(CollUtil.isNotEmpty(declarationTemps)){
            list = beanMapper.mapAsList(declarationTemps,DeclarationTempSimpleVO.class).stream().sorted(Comparator.comparing(DeclarationTempSimpleVO::getIsDefault).reversed()).collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 根据单据类型取消之前设置的默认模板
     */
    public void handleOldDefault(String billType){
        DeclarationTemp update = new DeclarationTemp();
        update.setIsDefault(Boolean.FALSE);
        declarationTempMapper.updateByExampleSelective(update, Example.builder(DeclarationTemp.class).where(TsfWeekendSqls.<DeclarationTemp>custom()
                .andEqualTo(false,DeclarationTemp::getBillType, billType)
                .andEqualTo(false,DeclarationTemp::getIsDefault,Boolean.TRUE)).build());
    }


}
